package com.crane.common.core.utils;

import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

/**
 * 随机数生成器类。
 */
public class RandomGenerator {

    /**
     * 随机器队列
     */
    private Queue<SecureRandom> randoms = new ConcurrentLinkedQueue<SecureRandom>();

    /**
     * 安全随机数算法
     */
    private String secureRandomAlgorithm = "SHA1PRNG";

    /**
     * 安全随机数提供者
     */
    private String secureRandomProvider = null;

    /**
     * 安全随机数类
     */
    private String secureRandomClass = null;

    /**
     * Create a new random number generator instance we should use for
     * generating session identifiers.
     */
    private SecureRandom createSecureRandom() {
        SecureRandom result = null;

        if (secureRandomClass != null) {
            try {
                // Construct and seed a new random number generator
                Class<?> clazz = Class.forName(secureRandomClass);
                result = (SecureRandom) clazz.newInstance();
            } catch (Exception e) {

            }
        }

        if (result == null) {
            // No secureRandomClass or creation failed. Use SecureRandom.
            try {
                if (secureRandomProvider != null && secureRandomProvider.length() > 0) {
                    result = SecureRandom.getInstance(secureRandomAlgorithm, secureRandomProvider);
                } else if (secureRandomAlgorithm != null && secureRandomAlgorithm.length() > 0) {
                    result = SecureRandom.getInstance(secureRandomAlgorithm);
                }
            } catch (NoSuchAlgorithmException e) {
            } catch (NoSuchProviderException e) {
            }
        }

        if (result == null) {
            // Invalid provider / algorithm
            try {
                result = SecureRandom.getInstance("SHA1PRNG");
            } catch (NoSuchAlgorithmException e) {
            }
        }

        if (result == null) {
            // Nothing works - use platform default
            result = new SecureRandom();
        }

        // Force seeding to take place
        result.nextInt();

        return result;
    }

    public int nextInt(int n) {
        SecureRandom random = randoms.poll();
        if (random == null) {
            random = createSecureRandom();
        }

        int r = random.nextInt(n);
        randoms.add(random);

        return r;
    }

    public long nextLong() {
        SecureRandom random = randoms.poll();
        if (random == null) {
            random = createSecureRandom();
        }

        long r = random.nextLong();
        randoms.add(random);

        return r;
    }

    public void nextBytes(byte[] bytes) {
        SecureRandom random = randoms.poll();
        if (random == null) {
            random = createSecureRandom();
        }

        random.nextBytes(bytes);
        randoms.add(random);
    }

    public String getSecureRandomAlgorithm() {
        return secureRandomAlgorithm;
    }

    public void setSecureRandomAlgorithm(String secureRandomAlgorithm) {
        this.secureRandomAlgorithm = secureRandomAlgorithm;
    }

    public String getSecureRandomProvider() {
        return secureRandomProvider;
    }

    public void setSecureRandomProvider(String secureRandomProvider) {
        this.secureRandomProvider = secureRandomProvider;
    }

    public String getSecureRandomClass() {
        return secureRandomClass;
    }

    public void setSecureRandomClass(String secureRandomClass) {
        this.secureRandomClass = secureRandomClass;
    }

}
